﻿//using System.Collections.Immutable;
//using System.Composition;
//using System.Linq;
//using System.Threading;
//using System.Threading.Tasks;
//using Microsoft.CodeAnalysis;
//using Microsoft.CodeAnalysis.CodeActions;
//using Microsoft.CodeAnalysis.CodeFixes;
//using Microsoft.CodeAnalysis.CSharp;
//using Microsoft.CodeAnalysis.CSharp.Syntax;
//using Microsoft.CodeAnalysis.Diagnostics;
//using UIOC.Attributes;
//using UIOC.CodeAnalysis.Diagnostics;
//using UIOC.CodeAnalysis.Extensions;
//using UIOC.CodeAnalysis.Helpers;

//namespace UIOC.CodeAnalysis.Analyzers;

//[DiagnosticAnalyzer(LanguageNames.CSharp)]
//internal sealed class AutoImplementObjectBaseTypeAnalyzer : DiagnosticAnalyzer {

//    private static void LogInfo(string message) {
//        SourceOutputHelper.LogInfoToSourceGenLog(DiagnosticSeverity.Info, $"[{nameof(AutoImplementObjectBaseTypeAnalyzer)}] {message}");
//    }

//    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
//        ImmutableArray.Create(AutoImplementObjectBaseTypeDiagnostic.Rule, AutoImplementArgumentTypeDiagnostic.Rule, AutoImplementSimplifyableDiagnostic.Rule);

//    public override void Initialize(AnalysisContext context) {
//        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
//        context.EnableConcurrentExecution();
//        context.RegisterSyntaxNodeAction(AnalyzeAttributeArgument, SyntaxKind.AttributeArgument);
//    }

//    private void AnalyzeAttributeArgument(SyntaxNodeAnalysisContext context) {
//        var compilation = context.SemanticModel.Compilation;
//        var assembly = compilation.Assembly;

//        if (assembly.IsIgnore()) {
//            return;
//        }

//        if (context.Node is not AttributeArgumentSyntax attributeArgumentSyntax) {
//            return;
//        }

//        var autoImplementAttributeSymbol = compilation.GetTypeByMetadataName(AttributeFullNames.AutoImplement);
//        if (autoImplementAttributeSymbol == null) {
//            return;
//        }

//        var attributeSyntax = attributeArgumentSyntax.AncestorsAndSelf().OfType<AttributeSyntax>().FirstOrDefault();
//        if (attributeSyntax == null) {
//            return;
//        }

//        var (attributeData, declaredSymbol) = attributeSyntax.GetAttributeData(context.SemanticModel);
//        if (attributeData == null) {
//            return;
//        }
//        var attributeClassSymbol = attributeData.AttributeClass;
//        if (!SymbolEqualityComparer.Default.Equals(attributeClassSymbol, autoImplementAttributeSymbol)) {
//            return;
//        }

//        var baseTypeTypedConstant = attributeData.ConstructorArguments.Length > 0 ? attributeData.ConstructorArguments[0] : attributeData.NamedArguments.FirstOrDefault(kv => kv.Key == nameof(AutoImplementAttribute.BaseType)).Value;

//        if (baseTypeTypedConstant.Kind != TypedConstantKind.Type
//            || baseTypeTypedConstant.Value == null
//            || baseTypeTypedConstant.Value is not ITypeSymbol baseTypeSymbol
//        ) {
//            return;
//        }

//        if (baseTypeSymbol.TypeKind != TypeKind.Class) {
//            context.ReportDiagnostic(Diagnostic.Create(
//                AutoImplementArgumentTypeDiagnostic.Rule,
//                attributeArgumentSyntax.GetLocation(),
//                baseTypeSymbol.Name));
//            return;
//        }

//        if (declaredSymbol is not INamedTypeSymbol interfaceSymbol) {
//            return;
//        }

//        var interfaceName = interfaceSymbol.Name;
//        var className = interfaceName.Substring(1);
//        var classFullName = $"{interfaceSymbol.ContainingNamespace.GetFullNamespaceName()}.{className}";
//        var classSymbol = compilation.GetTypeByMetadataName(classFullName);
//        if (classSymbol == null || classSymbol.BaseType == null) {
//            return;
//        }

//        var userSyntaxReferences = classSymbol.GetUserSyntaxReferences();
//        if (userSyntaxReferences == null || userSyntaxReferences.Count == 0) {
//            return;
//        }

//        INamedTypeSymbol userBaseTypeSymbol = null;
//        foreach (var userSyntaxReference in userSyntaxReferences) {
//            var syntaxTree = userSyntaxReference.SyntaxTree;
//            if (syntaxTree == null || userSyntaxReference.GetSyntax() is not ClassDeclarationSyntax classDeclaration) {
//                continue;
//            }

//            if (classDeclaration.BaseList != null) {
//                foreach (var baseType in classDeclaration.BaseList.Types) {
//                    var typeInfo = context.SemanticModel.GetTypeInfo(baseType.Type);
//                    if (typeInfo.Type is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.TypeKind == TypeKind.Class) {
//                        if (userBaseTypeSymbol != null) {
//                            return; // 多个继承类，交给官方分析器报错;
//                        }
//                        userBaseTypeSymbol = namedTypeSymbol;
//                        LogInfo($"{userBaseTypeSymbol.GetShortName()}...{attributeArgumentSyntax.GetLocation()}");
//                    }
//                }
//            }
//        }

//        if (userBaseTypeSymbol == null) {
//            return;
//        }

//        var systemObjectSymbol = compilation.GetSpecialType(SpecialType.System_Object);
//        if (SymbolEqualityComparer.Default.Equals(userBaseTypeSymbol, systemObjectSymbol)) {
//            return;
//        }

//        if (SymbolEqualityComparer.Default.Equals(userBaseTypeSymbol, baseTypeSymbol)) {
//            context.ReportDiagnostic(Diagnostic.Create(
//                 AutoImplementSimplifyableDiagnostic.Rule,
//                 attributeArgumentSyntax.GetLocation(),
//                 baseTypeSymbol.Name,
//                 interfaceSymbol.GetShortName(),
//                 classSymbol.GetShortName(),
//                 userBaseTypeSymbol.GetShortName()));
//            return;
//        }

//        context.ReportDiagnostic(Diagnostic.Create(
//            AutoImplementObjectBaseTypeDiagnostic.Rule,
//            attributeArgumentSyntax.GetLocation(),
//            baseTypeSymbol.Name,
//            interfaceSymbol.GetShortName(),
//            classSymbol.GetShortName(),
//            userBaseTypeSymbol.GetShortName()));
//    }
//}

//[Shared]
//[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AutoImplementSimplifySyntaxCodeFixProvider))]
//public class AutoImplementSimplifySyntaxCodeFixProvider : CodeFixProvider {

//    private static void LogInfo(string message) {
//        SourceOutputHelper.LogInfoToSourceGenLog(DiagnosticSeverity.Info, $"[{nameof(AutoImplementSimplifySyntaxCodeFixProvider)}] {message}");
//    }

//    public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AutoImplementSimplifyableDiagnostic.DiagnosticId, AutoImplementObjectBaseTypeDiagnostic.DiagnosticId);

//    public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

//    public override async Task RegisterCodeFixesAsync(CodeFixContext context) {
//        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
//        var diagnostic = context.Diagnostics.First();
//        var diagnosticSpan = diagnostic.Location.SourceSpan;

//        if (root.FindNode(diagnosticSpan) is not AttributeArgumentSyntax attributeArgumentSyntax)
//            return;

//        context.RegisterCodeFix(
//            CodeAction.Create(
//                title: "简化为 [AutoImplement]",
//                createChangedDocument: cancellationToken => SimplifyObjectCreation(context.Document, attributeArgumentSyntax, cancellationToken),
//                equivalenceKey: "SimplifyToNoBaseTypeArgument"
//            ),
//            diagnostic
//        );
//    }

//    private async Task<Document> SimplifyObjectCreation(Document document, AttributeArgumentSyntax attributeArgumentSyntax, CancellationToken cancellationToken) {
//        var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

//        var attributeSyntax = attributeArgumentSyntax.AncestorsAndSelf().OfType<AttributeSyntax>().FirstOrDefault();

//        var newSyntax = SyntaxFactory.Attribute(attributeSyntax.Name, null);

//        var newRoot = root.ReplaceNode(attributeSyntax, newSyntax);
//        return document.WithSyntaxRoot(newRoot);
//    }
//}